fix: persist delivered email body in MemberEmailDelivery - #2827
Merged
Conversation
premailer-rails converts messages to multipart/alternative during delivery, emptying the body container. The EmailDelivery concern read `mail.body.to_s` in an after_deliver callback, so every logged row had an empty body (439 of 439 rows in production). Read the html part instead so the audit log captures the delivered content.
mroderick
marked this pull request as ready for review
August 31, 2026 08:29
olleolleolle
approved these changes
Aug 31, 2026
Co-authored-by: Olle Jonsson <olle.jonsson@gmail.com>
mroderick
enabled auto-merge
August 31, 2026 08:47
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
member_email_deliveries.bodyhas never captured any content — all 439 rows in production are empty, so the email audit log cannot show what was actually sent.Root cause
premailer-railsregisters a Mail interceptor that runs during delivery: it converts the message tomultipart/alternative(adding a plain-text part and inlining CSS), which empties the body container.EmailDelivery#log_sent_emailthen runs in anafter_delivercallback and readsmail.body.to_s— the now-empty container — storing"".The emails themselves are unaffected: recipients receive complete
multipart/alternativemessages with both plain-text and HTML parts. Only the audit log is broken. Chaser dedup checks row existence, not body, so it works as before.Fix
Read the html part instead of the body container:
Pure plain-text mailers (no html part) fall back to
mail.bodyas before.Testing
Extended the
MemberMailer#chaserlogging spec to assert the persisted row has a body containing the template copy. Confirmed red→green: the assertion fails with""on master and passes with the fix. Full mailer specs and the three-month chaser service spec pass (85 examples), RuboCop clean.Context
Found while diagnosing chaser reliability for #2384 (chaser introduced in #2449 for #2383).